package cn.iocoder.yudao.module.system.service.gugu;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.gugu.gugu.CeeMajorInfo;
import cn.iocoder.yudao.module.system.controller.admin.gugu.vo.CeeMajorPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.gugu.vo.CeeMajorTreeVO;
import cn.iocoder.yudao.module.system.dal.dataobject.gugu.CeeMajorDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.gugu.CeeMajorMapper;
import cn.iocoder.yudao.module.system.framework.cache.CeeMajorCacheConfig;
import cn.iocoder.yudao.module.system.service.user.AdminUserServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAJOR_NOT_EXISTS;
import static cn.iocoder.yudao.module.system.framework.cache.CeeMajorCacheConfig.CACHE_NAME_BY_NAME_AND_LEVEL;
import static cn.iocoder.yudao.module.system.framework.cache.CeeMajorCacheConfig.CACHE_NAME_SEARCH_BY_NAME;
import static cn.iocoder.yudao.module.system.framework.cache.CeeMajorCacheConfig.CACHE_NAME_CATEGORY_COUNTS;

/**
 * 大学高校专业数据 Service 实现类
 */
@Service
@Validated
@Slf4j
public class CeeMajorServiceImpl implements CeeMajorService {

    @Resource
    private CeeMajorMapper ceeMajorMapper;
    @Autowired
    private AdminUserServiceImpl adminUserService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {CACHE_NAME_BY_NAME_AND_LEVEL, CACHE_NAME_SEARCH_BY_NAME, CACHE_NAME_CATEGORY_COUNTS}, allEntries = true)
    public int saveMajorInfoList(List<CeeMajorInfo> majorInfoList) {
        if (CollUtil.isEmpty(majorInfoList)) {
            return 0;
        }

        int savedCount = 0;
        for (CeeMajorInfo majorInfo : majorInfoList) {
            // 检查是否已存在相同专业代码的记录
            CeeMajorDO existingMajor = ceeMajorMapper.selectByMajorCode(majorInfo.getMajorCode());
            if (existingMajor != null) {
                // 如果已存在，则跳过
                continue;
            }

            // 转换为DO对象
            CeeMajorDO ceeMajorDO = convertToCeeMajorDO(majorInfo);

            // 保存到数据库
            ceeMajorMapper.insert(ceeMajorDO);
            savedCount++;
        }

        return savedCount;
    }

    @Override
    public CeeMajorDO getMajorByName(String majorName) {
        List<CeeMajorDO> majors = ceeMajorMapper.selectByMajorName(majorName);
        return majors.isEmpty() ? null : majors.get(0);
    }

    @Override
    @Cacheable(value = CACHE_NAME_BY_NAME_AND_LEVEL, key = "#majorName + ':' + #educationLevel", unless = "#result == null")
    public CeeMajorDO getMajorByNameAndEducationLevel(String majorName, String educationLevel) {
        log.debug("Cache miss for major by name and level: {}, {}", majorName, educationLevel);
        List<CeeMajorDO> majors = ceeMajorMapper.selectByMajorNameAndEducationLevel(majorName, educationLevel);
        return majors.isEmpty() ? null : majors.get(0);
    }

    @Override
    public CeeMajorDO getMajorByCode(String majorCode) {
        return ceeMajorMapper.selectByMajorCode(majorCode);
    }

    @Override
    public List<CeeMajorDO> getMajorListByKeywords(String keywords) {
        return ceeMajorMapper.selectListByKeywords(keywords);
    }

    @Override
    public PageResult<CeeMajorDO> getMajorPage(CeeMajorPageReqVO reqVO) {
        return ceeMajorMapper.selectPage(reqVO);
    }

    @Override
    public CeeMajorDO getMajor(Long id) {
        CeeMajorDO major = ceeMajorMapper.selectById(id);
        if (major == null) {
            throw ServiceExceptionUtil.exception(MAJOR_NOT_EXISTS);
        }
        return major;
    }

    @Override
    public List<String> getDisciplinaryCategories(String educationLevel) {
        return ceeMajorMapper.selectDistinctDisciplinaryCategories(educationLevel);
    }

    @Override
    public List<String> getDisciplinarySubCategories(String disciplinaryCategory, String educationLevel) {
        return ceeMajorMapper.selectDistinctDisciplinarySubCategories(disciplinaryCategory, educationLevel);
    }

    @Override
    public List<CeeMajorDO> getMajorsBySubCategory(String disciplinaryCategory, String disciplinarySubCategory, String educationLevel, String majorName) {
        return ceeMajorMapper.selectByDisciplinarySubCategory(disciplinaryCategory, disciplinarySubCategory, educationLevel, majorName);
    }

    @Override
    @Cacheable(value = CACHE_NAME_SEARCH_BY_NAME, key = "#majorName + ':' + #educationLevel", unless = "#result == null or #result.isEmpty()")
    public List<CeeMajorDO> searchMajorsByName(String majorName, String educationLevel) {
        log.debug("Cache miss for search major by name: {}, {}", majorName, educationLevel);
        return ceeMajorMapper.searchByMajorName(majorName, educationLevel);
    }

    @Override
    public Map<String, Object> getMajorTree(String educationLevel, String categoryId) {
        return getMajorTree(educationLevel, categoryId, null);
    }

    @Override
    public Map<String, Object> getMajorTree(String educationLevel, String categoryId, String majorName) {
        Map<String, Object> result = new HashMap<>();

        // 如果有专业名称搜索，则直接搜索专业
        if (StringUtils.hasText(majorName)) {
            List<CeeMajorDO> searchResults = searchMajorsByName(majorName, educationLevel);

            // 构建树形结构，按学科门类和子类分组
            CeeMajorTreeVO treeVO = new CeeMajorTreeVO();
            List<CeeMajorTreeVO.CategoryNode> categoryNodes = new ArrayList<>();

            // 使用 Map 分组数据
            Map<String, Map<String, List<CeeMajorDO>>> groupedMajors = new HashMap<>();

            // 分组搜索结果
            for (CeeMajorDO major : searchResults) {
                String category = major.getDisciplinaryCategory();
                String subCategory = major.getDisciplinarySubCategory();

                // 确保学科门类存在
                groupedMajors.putIfAbsent(category, new HashMap<>());

                // 确保学科子类存在
                Map<String, List<CeeMajorDO>> subCategoryMap = groupedMajors.get(category);
                subCategoryMap.putIfAbsent(subCategory, new ArrayList<>());

                // 添加专业
                subCategoryMap.get(subCategory).add(major);
            }

            // 构建树形结构
            for (Map.Entry<String, Map<String, List<CeeMajorDO>>> categoryEntry : groupedMajors.entrySet()) {
                String category = categoryEntry.getKey();
                Map<String, List<CeeMajorDO>> subCategoryMap = categoryEntry.getValue();

                // 检查该学科门类下是否有包含专业的子类
                boolean hasData = false;
                for (List<CeeMajorDO> majors : subCategoryMap.values()) {
                    if (!majors.isEmpty()) {
                        hasData = true;
                        break;
                    }
                }

                // 如果没有数据，则跳过该学科门类
                if (!hasData) {
                    continue;
                }

                CeeMajorTreeVO.CategoryNode categoryNode = new CeeMajorTreeVO.CategoryNode();
                categoryNode.setId(category);
                categoryNode.setName(category);
                categoryNode.setLoaded(true);

                List<CeeMajorTreeVO.SubCategoryNode> subCategoryNodes = new ArrayList<>();

                // 构建子类节点
                for (Map.Entry<String, List<CeeMajorDO>> subCategoryEntry : subCategoryMap.entrySet()) {
                    String subCategory = subCategoryEntry.getKey();
                    List<CeeMajorDO> majors = subCategoryEntry.getValue();

                    // 如果该子类下没有专业，则跳过
                    if (majors.isEmpty()) {
                        continue;
                    }

                    CeeMajorTreeVO.SubCategoryNode subCategoryNode = new CeeMajorTreeVO.SubCategoryNode();
                    subCategoryNode.setId(subCategory);
                    subCategoryNode.setName(subCategory);

                    List<CeeMajorTreeVO.MajorNode> majorNodes = new ArrayList<>();

                    // 构建专业节点
                    for (CeeMajorDO major : majors) {
                        CeeMajorTreeVO.MajorNode majorNode = new CeeMajorTreeVO.MajorNode();
                        majorNode.setId(major.getId());
                        majorNode.setName(major.getMajorName());
                        majorNode.setCode(major.getMajorCode());
                        majorNode.setEducationLevel(major.getEducationLevel());
                        majorNode.setIsRecommended(major.getIsRecommended());
                        majorNode.setCareerDirection(major.getCareerDirection());
                        majorNode.setMajorIntroduction(major.getMajorIntroduction());
                        majorNode.setGraduateScale(major.getGraduateScale());
                        majorNode.setMaleFemaleRatio(major.getMaleFemaleRatio());
                        majorNode.setRecommendSchools(major.getRecommendSchools());
                        majorNode.setCourses(major.getCourses());
                        majorNode.setDisciplinaryCategory(major.getDisciplinaryCategory());
                        majorNode.setDisciplinarySubCategory(major.getDisciplinarySubCategory());
                        majorNode.setCreateTime(major.getCreateTime());
                        majorNodes.add(majorNode);
                    }

                    subCategoryNode.setChildren(majorNodes);
                    subCategoryNode.setMajorCount(majorNodes.size());
                    subCategoryNodes.add(subCategoryNode);
                }

                categoryNode.setChildren(subCategoryNodes);
                // 计算该门类下的专业总数
                int totalMajorCount = subCategoryNodes.stream()
                        .mapToInt(subNode -> subNode.getMajorCount() != null ? subNode.getMajorCount() : 0)
                        .sum();
                categoryNode.setMajorCount(totalMajorCount);
                categoryNodes.add(categoryNode);
            }

            treeVO.setCategories(categoryNodes);
            result.put("tree", treeVO);
            result.put("isSearchResult", true);
            result.put("searchKeyword", majorName);

            return result;
        }

        // 正常的懒加载逻辑
        // 获取所有学科门类
        List<String> categories = getDisciplinaryCategories(educationLevel);
        if (CollUtil.isEmpty(categories)) {
            return result;
        }

        // 构建树形结构
        CeeMajorTreeVO treeVO = new CeeMajorTreeVO();
        List<CeeMajorTreeVO.CategoryNode> categoryNodes = new ArrayList<>();

        // 确定要加载的学科门类
        String targetCategory = null;
        if (StringUtils.hasText(categoryId)) {
            // 如果指定了学科门类 ID，则只加载该门类的数据
            targetCategory = categoryId;
        } else if (!categories.isEmpty()) {
            // 如果没有指定，则加载第一个门类的数据
            targetCategory = categories.get(0);
        }

        // 性能优化：批量查询所有门类的专业数量统计，避免重复查询
        long startTime = System.currentTimeMillis();
        Map<String, Integer> categoryMajorCounts = getCategoryMajorCounts(categories, educationLevel);
        long endTime = System.currentTimeMillis();
        log.debug("getCategoryMajorCounts took {} ms for {} categories", endTime - startTime, categories.size());

        // 遍历学科门类，添加门类 ID 和名称
        for (String category : categories) {
            // 只有当前门类是目标门类时，才加载其子类和专业数据
            if (category.equals(targetCategory)) {
                // 获取该学科门类下的所有学科子类
                List<String> subCategories = getDisciplinarySubCategories(category, educationLevel);
                List<CeeMajorTreeVO.SubCategoryNode> subCategoryNodes = new ArrayList<>();
                boolean hasData = false;

                // 遍历学科子类
                for (String subCategory : subCategories) {
                    // 获取该学科子类下的所有专业
                    List<CeeMajorDO> majors = getMajorsBySubCategory(category, subCategory, educationLevel, null);

                    // 如果该子类下没有专业，则跳过
                    if (majors.isEmpty()) {
                        continue;
                    }

                    hasData = true;

                    CeeMajorTreeVO.SubCategoryNode subCategoryNode = new CeeMajorTreeVO.SubCategoryNode();
                    subCategoryNode.setId(subCategory); // 使用学科子类名称作为 ID
                    subCategoryNode.setName(subCategory);

                    List<CeeMajorTreeVO.MajorNode> majorNodes = new ArrayList<>();

                    // 遍历专业
                    for (CeeMajorDO major : majors) {
                        CeeMajorTreeVO.MajorNode majorNode = new CeeMajorTreeVO.MajorNode();
                        majorNode.setId(major.getId());
                        majorNode.setName(major.getMajorName());
                        majorNode.setCode(major.getMajorCode());
                        majorNode.setEducationLevel(major.getEducationLevel());
                        majorNode.setIsRecommended(major.getIsRecommended());
                        majorNode.setCareerDirection(major.getCareerDirection());
                        majorNode.setMajorIntroduction(major.getMajorIntroduction());
                        majorNode.setGraduateScale(major.getGraduateScale());
                        majorNode.setMaleFemaleRatio(major.getMaleFemaleRatio());
                        majorNode.setRecommendSchools(major.getRecommendSchools());
                        majorNode.setCourses(major.getCourses());
                        majorNode.setDisciplinaryCategory(major.getDisciplinaryCategory());
                        majorNode.setDisciplinarySubCategory(major.getDisciplinarySubCategory());
                        majorNode.setCreateTime(major.getCreateTime());
                        majorNodes.add(majorNode);
                    }

                    subCategoryNode.setChildren(majorNodes);
                    subCategoryNode.setMajorCount(majorNodes.size());
                    subCategoryNodes.add(subCategoryNode);
                }

                // 如果该门类下有数据，才添加到结果中
                if (hasData) {
                    CeeMajorTreeVO.CategoryNode categoryNode = new CeeMajorTreeVO.CategoryNode();
                    categoryNode.setId(category); // 使用学科门类名称作为 ID
                    categoryNode.setName(category);
                    categoryNode.setChildren(subCategoryNodes);
                    categoryNode.setLoaded(true); // 标记已加载子节点数据
                    // 计算该门类下的专业总数
                    int totalMajorCount = subCategoryNodes.stream()
                            .mapToInt(subNode -> subNode.getMajorCount() != null ? subNode.getMajorCount() : 0)
                            .sum();
                    categoryNode.setMajorCount(totalMajorCount);
                    categoryNodes.add(categoryNode);
                }
            } else {
                // 对于非目标门类，使用预先查询的专业数量统计
                Integer majorCount = categoryMajorCounts.get(category);
                if (majorCount != null && majorCount > 0) {
                    CeeMajorTreeVO.CategoryNode categoryNode = new CeeMajorTreeVO.CategoryNode();
                    categoryNode.setId(category); // 使用学科门类名称作为 ID
                    categoryNode.setName(category);
                    categoryNode.setLoaded(false); // 标记未加载子节点数据
                    categoryNode.setMajorCount(majorCount);
                    categoryNodes.add(categoryNode);
                }
            }
        }

        treeVO.setCategories(categoryNodes);
        result.put("tree", treeVO);
        result.put("categories", categories);
        result.put("currentCategory", targetCategory);
        result.put("isSearchResult", false);

        return result;
    }

    @Override
    public Map<String, Object> getMajorTree(Long userId, String educationLevel, String categoryId) {
        Map<String, Object> result = new HashMap<>();

        // 获取用户信息
        AdminUserDO user = adminUserService.getUser(userId);
        if (user == null || !StringUtils.hasText(user.getRecommendedMajors())) {
            // 如果用户不存在或没有推荐专业，返回空结果
            return result;
        }

        // 获取用户的推荐专业数据
        String recommendedMajorsStr = user.getRecommendedMajors();

        // 尝试解析JSON格式的推荐专业数据
        try {
            // 判断是否为JSON格式
            if (recommendedMajorsStr.startsWith("{")) {
                // 直接使用JSON数据
                ObjectMapper objectMapper = new ObjectMapper();
                CeeMajorTreeVO treeVO = objectMapper.readValue(recommendedMajorsStr, CeeMajorTreeVO.class);

                // 如果指定了学科门类 ID，需要过滤数据
                if (StringUtils.hasText(categoryId)) {
                    // 过滤出指定的学科门类
                    List<CeeMajorTreeVO.CategoryNode> filteredCategories = treeVO.getCategories().stream()
                            .filter(node -> node.getId().equals(categoryId))
                            .collect(Collectors.toList());

                    // 创建新的树形结构对象
                    CeeMajorTreeVO filteredTreeVO = new CeeMajorTreeVO();
                    filteredTreeVO.setCategories(filteredCategories);
                    treeVO = filteredTreeVO;
                }

                // 获取所有学科门类的ID
                List<String> categories = treeVO.getCategories().stream()
                        .map(CeeMajorTreeVO.CategoryNode::getId)
                        .collect(Collectors.toList());

                // 确定当前选中的学科门类
                String targetCategory = null;
                if (StringUtils.hasText(categoryId)) {
                    targetCategory = categoryId;
                } else if (!categories.isEmpty()) {
                    targetCategory = categories.get(0);
                }

                // 设置加载状态
                for (CeeMajorTreeVO.CategoryNode node : treeVO.getCategories()) {
                    if (node.getId().equals(targetCategory)) {
                        node.setLoaded(true);
                    } else {
                        node.setLoaded(false);
                        // 如果不是目标门类，清空子节点数据
                        node.setChildren(null);
                    }
                }

                result.put("tree", treeVO);
                result.put("categories", categories);
                result.put("currentCategory", targetCategory);
                result.put("isSearchResult", false);
                result.put("isRecommendedMajors", true);
                result.put("recommendedMajorsCount", countMajors(treeVO));

                return result;
            }
        } catch (Exception e) {
            // JSON解析失败，回退到旧的处理方式
//            log.warn("Failed to parse recommended majors as JSON for user ID {}, falling back to comma-separated format", userId, e);
        }

        // 如果不是JSON格式，使用旧的逗号分隔字符串处理方式
        String[] recommendedMajorNames = recommendedMajorsStr.split(",");

        // 构建树形结构，按学科门类和子类分组
        CeeMajorTreeVO treeVO = new CeeMajorTreeVO();
        List<CeeMajorTreeVO.CategoryNode> categoryNodes = new ArrayList<>();

        // 使用 Map 分组数据
        Map<String, Map<String, List<CeeMajorDO>>> groupedMajors = new HashMap<>();

        // 查询并分组推荐专业
        for (String majorName : recommendedMajorNames) {
            // 尝试多种匹配方式查找专业
            CeeMajorDO major = findMajorWithBracketSupport(majorName, educationLevel);
            if (major == null) {
                continue; // 如果找不到匹配，跳过此专业
            }

            String category = major.getDisciplinaryCategory();
            String subCategory = major.getDisciplinarySubCategory();

            // 确保学科门类存在
            groupedMajors.putIfAbsent(category, new HashMap<>());

            // 确保学科子类存在
            Map<String, List<CeeMajorDO>> subCategoryMap = groupedMajors.get(category);
            subCategoryMap.putIfAbsent(subCategory, new ArrayList<>());

            // 添加专业
            subCategoryMap.get(subCategory).add(major);
        }

        // 获取所有学科门类（用于构建完整的树形结构）
        List<String> categories = new ArrayList<>(groupedMajors.keySet());
        if (CollUtil.isEmpty(categories)) {
            return result;
        }

        // 确定要加载的学科门类
        String targetCategory = null;
        if (StringUtils.hasText(categoryId)) {
            // 如果指定了学科门类 ID，则只加载该门类的数据
            targetCategory = categoryId;
        } else if (!categories.isEmpty()) {
            // 如果没有指定，则加载第一个门类的数据
            targetCategory = categories.get(0);
        }

        // 构建树形结构
        for (Map.Entry<String, Map<String, List<CeeMajorDO>>> categoryEntry : groupedMajors.entrySet()) {
            String category = categoryEntry.getKey();
            Map<String, List<CeeMajorDO>> subCategoryMap = categoryEntry.getValue();

            // 检查该学科门类下是否有包含专业的子类
            boolean hasData = false;
            for (List<CeeMajorDO> majors : subCategoryMap.values()) {
                if (!majors.isEmpty()) {
                    hasData = true;
                    break;
                }
            }

            // 如果没有数据，则跳过该学科门类
            if (!hasData) {
                continue;
            }

            CeeMajorTreeVO.CategoryNode categoryNode = new CeeMajorTreeVO.CategoryNode();
            categoryNode.setId(category);
            categoryNode.setName(category);

            // 只有当前门类是目标门类时，才加载其子类和专业数据
            if (category.equals(targetCategory)) {
                List<CeeMajorTreeVO.SubCategoryNode> subCategoryNodes = new ArrayList<>();

                // 构建子类节点
                for (Map.Entry<String, List<CeeMajorDO>> subCategoryEntry : subCategoryMap.entrySet()) {
                    String subCategory = subCategoryEntry.getKey();
                    List<CeeMajorDO> majors = subCategoryEntry.getValue();

                    // 如果该子类下没有专业，则跳过
                    if (majors.isEmpty()) {
                        continue;
                    }

                    CeeMajorTreeVO.SubCategoryNode subCategoryNode = new CeeMajorTreeVO.SubCategoryNode();
                    subCategoryNode.setId(subCategory);
                    subCategoryNode.setName(subCategory);

                    List<CeeMajorTreeVO.MajorNode> majorNodes = new ArrayList<>();

                    // 构建专业节点
                    for (CeeMajorDO major : majors) {
                        CeeMajorTreeVO.MajorNode majorNode = new CeeMajorTreeVO.MajorNode();
                        majorNode.setId(major.getId());
                        majorNode.setName(major.getMajorName());
                        majorNode.setCode(major.getMajorCode());
                        majorNode.setEducationLevel(major.getEducationLevel());
                        majorNode.setIsRecommended(major.getIsRecommended());
                        majorNode.setCareerDirection(major.getCareerDirection());
                        majorNode.setMajorIntroduction(major.getMajorIntroduction());
                        majorNode.setGraduateScale(major.getGraduateScale());
                        majorNode.setMaleFemaleRatio(major.getMaleFemaleRatio());
                        majorNode.setRecommendSchools(major.getRecommendSchools());
                        majorNode.setCourses(major.getCourses());
                        majorNode.setDisciplinaryCategory(major.getDisciplinaryCategory());
                        majorNode.setDisciplinarySubCategory(major.getDisciplinarySubCategory());
                        majorNode.setCreateTime(major.getCreateTime());
                        majorNodes.add(majorNode);
                    }

                    subCategoryNode.setChildren(majorNodes);
                    subCategoryNode.setMajorCount(majorNodes.size());
                    subCategoryNodes.add(subCategoryNode);
                }

                categoryNode.setChildren(subCategoryNodes);
                categoryNode.setLoaded(true); // 标记已加载子节点数据
                // 计算该门类下的专业总数
                int totalMajorCount = subCategoryNodes.stream()
                        .mapToInt(subNode -> subNode.getMajorCount() != null ? subNode.getMajorCount() : 0)
                        .sum();
                categoryNode.setMajorCount(totalMajorCount);
            } else {
                categoryNode.setLoaded(false); // 标记未加载子节点数据
                // 计算该门类下的专业总数
                int totalMajorCount = subCategoryMap.values().stream()
                        .mapToInt(List::size)
                        .sum();
                categoryNode.setMajorCount(totalMajorCount);
            }

            categoryNodes.add(categoryNode);
        }

        treeVO.setCategories(categoryNodes);
        result.put("tree", treeVO);
        result.put("categories", categories);
        result.put("currentCategory", targetCategory);
        result.put("isSearchResult", false);
        result.put("isRecommendedMajors", true);
        result.put("recommendedMajorsCount", recommendedMajorNames.length);

        return result;
    }

    /**
     * 计算树形结构中的专业总数
     *
     * @param treeVO 树形结构
     * @return 专业总数
     */
    private int countMajors(CeeMajorTreeVO treeVO) {
        if (treeVO == null || treeVO.getCategories() == null) {
            return 0;
        }

        return Math.toIntExact(treeVO.getCategories().stream()
                .filter(category -> category.getChildren() != null)
                .flatMap(category -> category.getChildren().stream())
                .filter(subCategory -> subCategory.getChildren() != null)
                .flatMap(subCategory -> subCategory.getChildren().stream())
                .count());
    }

    @Override
    public List<CeeMajorDO> getRecommendedMajors(String educationLevel) {
        LambdaQueryWrapperX<CeeMajorDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.eq(CeeMajorDO::getIsRecommended, true);
        if (StringUtils.hasText(educationLevel)) {
            wrapper.eq(CeeMajorDO::getEducationLevel, educationLevel);
        }
        return ceeMajorMapper.selectList(wrapper);
    }

    /**
     * 批量查询各学科门类的专业数量统计（性能优化）
     *
     * @param categories 学科门类列表
     * @param educationLevel 教育级别
     * @return 门类专业数量映射
     */
    @Cacheable(value = CACHE_NAME_CATEGORY_COUNTS, key = "#categories.toString() + ':' + #educationLevel", unless = "#result == null or #result.isEmpty()")
    public Map<String, Integer> getCategoryMajorCounts(List<String> categories, String educationLevel) {
        log.debug("Cache miss for category major counts: categories={}, educationLevel={}", categories, educationLevel);
        Map<String, Integer> categoryMajorCounts = new HashMap<>();

        if (CollUtil.isEmpty(categories)) {
            return categoryMajorCounts;
        }

        // 为每个门类查询专业数量，但使用COUNT查询而不是查询全部数据
        for (String category : categories) {
            LambdaQueryWrapperX<CeeMajorDO> wrapper = new LambdaQueryWrapperX<>();
            wrapper.eq(CeeMajorDO::getDisciplinaryCategory, category);
            if (StringUtils.hasText(educationLevel)) {
                wrapper.eq(CeeMajorDO::getEducationLevel, educationLevel);
            }

            // 只查询数量，不查询具体数据，这比查询全部数据再统计要快得多
            Long count = ceeMajorMapper.selectCount(wrapper);
            categoryMajorCounts.put(category, count.intValue());
        }

        log.debug("Category major counts result: {}", categoryMajorCounts);
        return categoryMajorCounts;
    }

    /**
     * 将 CeeMajorInfo 转换为 CeeMajorDO
     *
     * @param majorInfo 专业信息
     * @return 专业DO对象
     */
    private CeeMajorDO convertToCeeMajorDO(CeeMajorInfo majorInfo) {
        if (majorInfo == null) {
            return null;
        }

        // 转换课程列表
        List<CeeMajorDO.Course> courses = new ArrayList<>();
        if (CollUtil.isNotEmpty(majorInfo.getCourses())) {
            for (CeeMajorInfo.Course course : majorInfo.getCourses()) {
                CeeMajorDO.Course doCourse = new CeeMajorDO.Course();
                doCourse.setCourseName(course.getCourseName());
                doCourse.setCourseDifficulty(course.getCourseDifficulty());
                courses.add(doCourse);
            }
        }

        // 构建并返回DO对象
        return CeeMajorDO.builder()
                .educationLevel(majorInfo.getEducationLevel())
                .disciplinaryCategory(majorInfo.getDisciplinaryCategory())
                .disciplinarySubCategory(majorInfo.getDisciplinarySubCategory())
                .majorCode(majorInfo.getMajorCode())
                .majorName(majorInfo.getMajorName())
                .majorIntroduction(majorInfo.getMajorIntroduction())
                .courses(courses)
                .graduateScale(majorInfo.getGraduateScale())
                .maleFemaleRatio(majorInfo.getMaleFemaleRatio())
                .recommendSchools(majorInfo.getRecommendSchools())
                .jobWorkingDetails(majorInfo.getJobWorkingDetails())
                .build();
    }

    /**
     * 支持括号内容匹配的专业查找方法
     * @param majorName 专业名称
     * @param educationLevel 教育级别
     * @return 匹配的专业信息
     */
    private CeeMajorDO findMajorWithBracketSupport(String majorName, String educationLevel) {
        if (!StringUtils.hasText(majorName)) {
            return null;
        }

        // 1. 首先尝试精确匹配
        CeeMajorDO exactMatch = getMajorByNameAndEducationLevel(majorName, educationLevel);
        if (exactMatch != null) {
            return exactMatch;
        }

        // 2. 尝试去除括号后匹配（支持中文括号和英文括号）
        String cleanMajorName = majorName.replaceAll("[\\(（].*?[\\)）]", "").trim();
        if (!cleanMajorName.equals(majorName)) {
            CeeMajorDO cleanMatch = getMajorByNameAndEducationLevel(cleanMajorName, educationLevel);
            if (cleanMatch != null) {
                return cleanMatch;
            }
        }

        // 3. 提取括号内的专业名称进行匹配
        List<String> bracketNames = extractMajorNamesFromBrackets(majorName);
        for (String bracketName : bracketNames) {
            CeeMajorDO bracketMatch = getMajorByNameAndEducationLevel(bracketName, educationLevel);
            if (bracketMatch != null) {
                return bracketMatch;
            }
        }

        // 4. 如果都没有找到，返回null
        return null;
    }

    /**
     * 提取专业名称中括号内的所有专业名称
     * 支持中文括号（）和英文括号()
     * 例如：计算机类(计算机科学与技术、软件工程) -> [计算机科学与技术, 软件工程]
     * @param majorName 包含括号的专业名称
     * @return 括号内的专业名称列表
     */
    private List<String> extractMajorNamesFromBrackets(String majorName) {
        List<String> result = new ArrayList<>();

        if (!StringUtils.hasText(majorName)) {
            return result;
        }

        // 同时支持中文括号（）和英文括号()
        int startIndex = -1;
        int endIndex = -1;

        // 查找英文括号
        int englishStart = majorName.indexOf('(');
        int englishEnd = majorName.lastIndexOf(')');

        // 查找中文括号
        int chineseStart = majorName.indexOf('（');
        int chineseEnd = majorName.lastIndexOf('）');

        // 选择最早出现的开始括号
        if (englishStart > 0 && chineseStart > 0) {
            startIndex = Math.min(englishStart, chineseStart);
        } else if (englishStart > 0) {
            startIndex = englishStart;
        } else if (chineseStart > 0) {
            startIndex = chineseStart;
        }

        // 选择对应的结束括号
        if (startIndex == englishStart && englishEnd > startIndex) {
            endIndex = englishEnd;
        } else if (startIndex == chineseStart && chineseEnd > startIndex) {
            endIndex = chineseEnd;
        }

        if (startIndex > 0 && endIndex > startIndex) {
            String bracketContent = majorName.substring(startIndex + 1, endIndex);

            // 按照中文顿号、逗号等分隔符分割
            String[] parts = bracketContent.split("[、，,]");

            for (String part : parts) {
                String trimmed = part.trim();
                if (!trimmed.isEmpty()) {
                    result.add(trimmed);
                }
            }
        }

        return result;
    }
}
